昨天將活動報名以及儲存報名者資訊的功能做好了,而今天要再加上取消報名的功能,以及在頁面顯示當前活動報名人數。
Repository 先前已經完成了刪除報名使用者資料功能了,但還要再新增一個撈取該活動所有 EventsEnroll 的 Function,讓後續可以在 Services 新增一個比對當前使用者的報名資料是否存在於 EventsEnroll 內。
建立以「活動ID」撈取 EventsEnroll 的 Function:
public async Task<IEnumerable<EventsEnroll>> GetEventsEnrollByEventIdAsync(int eventId)
{
            var eventsEnrolls = await _appDbContext.EventsEnroll.Where(
                ee => ee.Events.Id == eventId
                ).ToListAsync();
            return eventsEnrolls;
}
建立與 GetEventsEnrollByEventIdAsync() 取得的活動比對當前使用者是否被存在於資料內的 Function:
public async Task<bool> IsUserAlreadyEnroll(int id, string userId)
        {
            try
            {
                if(id > 0 && !string.IsNullOrEmpty(userId))
                {
                    var eventsEnrolls = await _eventsRepository.GetEventsEnrollsByEventIdAsync(id);
                    var userInEnroll = eventsEnrolls.Where(
                        ee => ee.ApplicationUserId == userId
                        ).FirstOrDefault();
                    if(userInEnroll == null)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    throw new Exception("判斷使用者是否在活動報名資料內錯誤。 ID not valid");
                }
            }
            catch (Exception)
            {
                throw new Exception("判斷使用者是否在活動報名資料內錯誤。");
            }
        }
修正 EventsEnroll 在判斷是否符合可報名條件(在報名時間內 & 是否已額滿)的邏輯,加入是否已報名:
if (isInEventsSalesTime == true && isApplicationLimitedQtyFull == false
        && !await EventsApplyServices.IsUserAlreadyEnroll((int)id, userId))
{
    await _eventsRepository.SaveUserInfoToEventsEnrollAsync(EventsEnroll);
    TempData["Message"] = "報名成功";
}
else
{
    TempData["Message"] = "報名失敗";
}
public async Task<IActionResult> Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }
            var @event = await _eventsRepository.GetEventByIdAsync(id);
            if (@event == null)
            {
                return NotFound();
            }
            EventsApplyServices EventsApplyServices = new EventsApplyServices(_eventsRepository);
            var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
            if (!await EventsApplyServices.IsApplicationLimitedQtyFull(@event) && EventsApplyServices.IsInEventsSalesTime(@event))
            {
                if (await EventsApplyServices.IsUserAlreadyEnroll((int)id, userId))
                {
                    ViewData["EnrollBtn"] = 2;
                }
                else
                {
                    ViewData["EnrollBtn"] = 1;
                }
            }
            else
            {
                ViewData["EnrollBtn"] = 3;
            }
            return View(@event);
        }
新增 CancelEventsEnroll 取消報名 Action:
[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> CancelEventsEnroll(int? id)
        {
            Events Event = new Events();
            try
            {
                if (id != null)
                {
                    Event = await _eventsRepository.GetEventByIdAsync(id);
                    EventsApplyServices EventsApplyServices = new EventsApplyServices(_eventsRepository);
                    var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
                    EventsEnroll EventsEnroll = new EventsEnroll()
                    {
                        Events = Event,
                        ApplicationUserId = userId
                    };
                    if (Event != null && await EventsApplyServices.IsUserAlreadyEnroll((int)id, userId))
                    {
                        await _eventsRepository.DeleteUserInfoFromEventsEnrollAsync(EventsEnroll);
                        TempData["Message"] = "取消報名成功";
                    }
                    else
                    {
                        TempData["Message"] = "取消報名失敗";
                    }
                }
                else
                {
                    return BadRequest();
                }
            }
            catch (Exception)
            {
                throw new Exception("取消報名失敗");
            }
            return RedirectToAction("Details", Event);
        }
將報名按鈕加入邏輯,可直接顯示是否允許報名,並將 Form Tag 移到判斷式內,使判斷式可動態切換要使用的 Action:
@{
        switch ((int)ViewData["EnrollBtn"])
        {
            case 1:
                <form asp-action="EventsEnroll" method="post" style="display:inline;">
                    <input type="hidden" asp-for="Id" />
                    <input type="submit" value="報名" class="btn btn-primary" />
                </form>
                break;
            case 2:
                <form asp-action="CancelEventsEnroll" method="post" style="display:inline;">
                    <input type="submit" value="取消報名" class="btn btn-danger" />
                    <input type="hidden" asp-for="Id" />
                </form>
                break;
            default:
                <input type="button" value="無法報名" class="btn btn-primary" disabled/>
                break;
        }
    }
不在票券販賣時間內時,顯示無法報名:
在票券販賣時間內時且尚未報名,顯示報名:
在票券販賣時間內時且已經報名,顯示取消報名:
今天將取消報名與不在時間內無法報名的邏輯做好了,明天預計會使用一下 Partial View,將提示訊息用 Partial View 的方式來顯示。
也預計將一些按鈕是否顯示的部分做好,例如說只有活動舉辦者才可以顯示編輯按鈕等等的。
那麼我們明天見!